#pragma once

#include<iostream>
#include<vector>
#include"Sem.hpp"
#include"Mutex.hpp"

static const int gcap = 5;
using namespace MutexModule;
using namespace SemMoudle;

template <typename T>
class RingQueue
{
public:
    RingQueue(int cap = gcap)
        : _cap(cap),    
        _rq(cap),
        _blank_sem(cap),
        _p_step(0),
        _date_sem(0),
        _c_step(0)
    { }

    void Eququq(const T & in)
    {
        _blank_sem.P();
        {
            LockGuard lockguard(_pmutex);
            _rq[_p_step] = in;
            ++_p_step;
            _p_step %= _cap;
        }
        _date_sem.V();
    }    
    void Pop(T* out)
    {
        _date_sem.P();
        {
            LockGuard lockguard(_cmutex);
            *out = _rq[_c_step];
            ++_c_step;
            _c_step %= _cap;
        }
        _blank_sem.V();
    }

    ~RingQueue()
    {}
private:
    std::vector<T> _rq;
    int _cap;
    //生产者
    Sem _blank_sem;
    int _p_step;

    //消费者
    Sem _date_sem;
    int _c_step;

    Mutex _cmutex;
    Mutex _pmutex;

};
